package cd.cdyb.sms.task;


import cd.cdyb.sms.dao.CompanyDao;
import cd.cdyb.sms.dao.InventoryFlowDao;
import cd.cdyb.sms.domain.Company;
import cd.cdyb.sms.service.RedisService;
import cd.cdyb.sms.utils.CacheUtils;
import cd.cdyb.sms.utils.RedissonUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@EnableAsync          //开启异步执行
public class InventoryScheduledTask {

    @Resource
    private CompanyDao companyDao;

    @Resource
    private InventoryFlowDao inventoryFlowDao;

    @Resource
    private RedisService redisService;

    @Resource
    private RedissonUtil redissonUtil;

    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void updateInventory() {
        log.info("-----------库存结算任务开始------------");
        LambdaQueryWrapper<Company> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Company::getIsDeleted, false);
        List<Company> companyList = companyDao.selectList(wrapper);
        RLock lock = redissonUtil.getLock("UPDATE_COMPANY");
        try {
            // 尝试加锁，最多等待5秒，上锁以后10秒自动解锁
            boolean isOk = lock.tryLock(5, 10, TimeUnit.SECONDS);
            if (!isOk) {
                // 获取分布式锁失败，可以进行抛出获取锁失败的提示等，根据业务来
                log.info("获取分布式锁失败");
                return;
            }
            Thread.sleep(2000);
            for (Company company : companyList) {

                LocalDateTime endLocalDateTime = LocalDateTime.now();
//                LocalDateTime endLocalDateTime = now.minusMinutes(1);
                LocalDateTime startLocalDateTime = endLocalDateTime.minusMinutes(10);
                String companyKey = company.getCompanyKey();
                //暂时只统计行业短信
                Integer incInventoryFlowCount = inventoryFlowDao.getInventoryFlowCountByCompanyId(companyKey, 1, 6, startLocalDateTime, endLocalDateTime);
                Integer reduceInventoryFlowCount = inventoryFlowDao.getInventoryFlowCountByCompanyId(companyKey, 0, 6, startLocalDateTime, endLocalDateTime);
                int count = incInventoryFlowCount - reduceInventoryFlowCount;
                Integer industryCount = company.getIndustryCount();
                industryCount += count;
                company.setIndustryCount(industryCount);

                //暂时只统计行业短信
                Integer incMarketInventoryFlowCount = inventoryFlowDao.getInventoryFlowCountByCompanyId(company.getCompanyKey(), 1, 5, startLocalDateTime, endLocalDateTime);
                Integer reduceMarketInventoryFlowCount = inventoryFlowDao.getInventoryFlowCountByCompanyId(company.getCompanyKey(), 0, 5, startLocalDateTime, endLocalDateTime);
                int count2 = incMarketInventoryFlowCount - reduceMarketInventoryFlowCount;
                Integer marketingCount = company.getMarketingCount();
                marketingCount += count2;
                company.setMarketingCount(marketingCount);

                companyDao.updateById(company);
                log.info("[{}]库存更新，行业消费[{}],行业充值[{}], 合计[{}]", company.getCompanyName(), reduceInventoryFlowCount, incInventoryFlowCount, industryCount);

                log.info("[{}]库存更新，剩余行业[{}],剩余营销[{}]", company.getCompanyName(), industryCount, marketingCount);

                // 将为记录的流水变为记录
                inventoryFlowDao.updateInventoryFlowStatus(companyKey, startLocalDateTime, endLocalDateTime);

                //判断缓存和库存是否一致，不一致则更新
                Integer o = (Integer) redisService.vGet(CacheUtils.CacheName.COMPANY_SMS_INVENTORY, companyKey + ":" + 5);
                if (o != null && !marketingCount.equals(o)) {
                    log.info("[{}]营销库存不一致，更新redis", company.getCompanyName());
                    redisService.removeKey(CacheUtils.CacheName.COMPANY_SMS_INVENTORY, companyKey + ":" + 5);
                }

                Integer o1 = (Integer) redisService.vGet(CacheUtils.CacheName.COMPANY_SMS_INVENTORY, companyKey + ":" + 6);
                if (o1 != null && industryCount.compareTo(o1) != 0) {
                    log.info("[{}]行业库存不一致redis现在[{}],实际库存[{}]，更新redis", company.getCompanyName(), o1, industryCount);
                    redisService.removeKey(CacheUtils.CacheName.COMPANY_SMS_INVENTORY, companyKey + ":" + 6);
                }


            }
        } catch (InterruptedException e) {
            // 如果10s没有执行完，锁会自动释放，这里抛出异常
            Thread.currentThread().interrupt();
        } finally {
            // 如果10s没有执行完，锁会自动释放，这里抛出异常，操作失败，需要对数据回滚
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        log.info("-----------库存结算任务结束------------");
    }


}
